package com.gpc.hexapods.gl;

import android.content.Context;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.opengl.Matrix;

import com.gpc.hexapods.data.Point;
import com.gpc.hexapods.layer.BodyLayer;
import com.gpc.hexapods.layer.LegLayer;
import com.gpc.hexapods.utils.MatrixUtils;
import com.gpc.hexapods.utils.ShaderUtils;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

public class GLRender implements GLSurfaceView.Renderer {

    public final static String TAG = "GLRender";

    public final static int X = 0;
    public final static int Y = 1;
    public final static int Z = 2;

    private Context mContext;

    private int mProgramId;
    private int mGlUMatrix;
    private int mPositionHandle;
    private int mColorHandle;

    private float[] mMatrix;

    private BodyLayer mBodyLayer;
    private LegLayer m1LegLayer;
    private LegLayer m2LegLayer;
    private LegLayer m3LegLayer;
    private LegLayer m4LegLayer;
    private LegLayer m5LegLayer;
    private LegLayer m6LegLayer;

    public GLRender(Context context) {
        mContext = context;
        mBodyLayer = new BodyLayer();
        m1LegLayer = new LegLayer(new Point(-0.4f, 0.75f), 120, 60, 45);
        m2LegLayer = new LegLayer(new Point(-0.65f, 0), 180, 60, 45);
        m3LegLayer = new LegLayer(new Point(-0.4f, -0.75f), 240, 60, 45);
        m4LegLayer = new LegLayer(new Point(0.4f, 0.75f), 60, 60, 45);
        m5LegLayer = new LegLayer(new Point(0.65f, 0), 0, 60, 45);
        m6LegLayer = new LegLayer(new Point(0.4f, -0.75f), 300, 60, 45);
    }

    public void setData() {
        m1LegLayer.setAngle(180, 45, 60);
        m2LegLayer.setAngle(180, 45, 60);
        m3LegLayer.setAngle(180, 45, 60);
        m4LegLayer.setAngle(0, 45, 60);
        m5LegLayer.setAngle(0, 45, 60);
        m6LegLayer.setAngle(0, 45, 60);
    }

    public LegLayer getM1LegLayer() {
        return m1LegLayer;
    }

    public LegLayer getM2LegLayer() {
        return m2LegLayer;
    }

    public LegLayer getM3LegLayer() {
        return m3LegLayer;
    }

    public LegLayer getM4LegLayer() {
        return m4LegLayer;
    }

    public LegLayer getM5LegLayer() {
        return m5LegLayer;
    }

    public LegLayer getM6LegLayer() {
        return m6LegLayer;
    }

    public void set135LegLayer(float bAngle, float cAngle) {
        m1LegLayer.setAngle(120, bAngle, cAngle);
        m3LegLayer.setAngle(240, bAngle, cAngle);
        m5LegLayer.setAngle(0, bAngle, cAngle);
    }

    public void set246LegLayer(float bAngle, float cAngle) {
        m2LegLayer.setAngle(180, bAngle, cAngle);
        m4LegLayer.setAngle(60, bAngle, cAngle);
        m6LegLayer.setAngle(300, bAngle, cAngle);
    }

    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        mProgramId = ShaderUtils.createProgram(mContext.getResources(),
                "vertex.glsl", "fragment.glsl");
        mGlUMatrix = GLES20.glGetUniformLocation(mProgramId, "uMatrix");
        mPositionHandle = GLES20.glGetAttribLocation(mProgramId, "aPosition");
        mColorHandle = GLES20.glGetAttribLocation(mProgramId, "aColor");

        mBodyLayer.setHandle(mPositionHandle, mColorHandle);
        m1LegLayer.setHandle(mPositionHandle, mColorHandle);
        m2LegLayer.setHandle(mPositionHandle, mColorHandle);
        m3LegLayer.setHandle(mPositionHandle, mColorHandle);
        m4LegLayer.setHandle(mPositionHandle, mColorHandle);
        m5LegLayer.setHandle(mPositionHandle, mColorHandle);
        m6LegLayer.setHandle(mPositionHandle, mColorHandle);

        GLES20.glEnable(GLES20.GL_DEPTH_TEST);
    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        int x = 0;
        int y = 0;
        if (width < height) {
            x = (width - height) / 2;
            width = height;
        } else {
            y = (height - width) / 2;
            height = width;
        }
        GLES20.glViewport(x, y, width, height);

        mMatrix = MatrixUtils.getOriginalMatrix();
        Matrix.scaleM(mMatrix, 0, 0.2f, 0.2f, 0.2f);
    }

    public void rotate(int axis, float angle) {
        switch (axis) {
            case X:
                Matrix.rotateM(mMatrix, 0, angle, 1, 0, 0);
                break;
            case Y:
                Matrix.rotateM(mMatrix, 0, angle, 0, 1, 0);
                break;
            case Z:
                Matrix.rotateM(mMatrix, 0, angle, 0, 0, 1);
                break;
        }

    }

    @Override
    public void onDrawFrame(GL10 gl) {
        GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
        GLES20.glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
        GLES20.glUseProgram(mProgramId);
        GLES20.glUniformMatrix4fv(mGlUMatrix, 1, false, mMatrix, 0);
        GLES20.glEnableVertexAttribArray(mPositionHandle);
        GLES20.glEnableVertexAttribArray(mColorHandle);

        mBodyLayer.onDraw();
        m1LegLayer.onDraw();
        m2LegLayer.onDraw();
        m3LegLayer.onDraw();
        m4LegLayer.onDraw();
        m5LegLayer.onDraw();
        m6LegLayer.onDraw();

        GLES20.glDisableVertexAttribArray(mPositionHandle);
        GLES20.glDisableVertexAttribArray(mColorHandle);
    }

}
